;   This program is free software: you can redistribute it and/or modify
;   it under the terms of the GNU General Public License as published by
;   the Free Software Foundation, either version 3 of the License, or
;   (at your option) any later version.
;
;   This program is distributed in the hope that it will be useful,
;   but WITHOUT ANY WARRANTY; without even the implied warranty of
;   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;   GNU General Public License for more details.
;
;   You should have received a copy of the GNU General Public License
;   along with this program.  If not, see <http://www.gnu.org/licenses/>.
;
;程序名称:4chess.asm
;功能:四子棋(棋盘游戏)
;环境:16BIT DOS实模式(windows/dos或dosbox)最好全屏
;编译器:MASM 5.1-6X (这个是com格式，masm5.x须用EXE2BIN 4CHESS.EXE 4CHESS.COM，Masm6.x须加入：ml /ＡＴ参数
;用法:看说明
;返回值:没有
;破坏寄存器:不适用
;
;简易版四子棋简介:
;四子棋是一款普遍流行的简易型桌面游戏，据说，虎克船长曾因专注于此游戏而长期隐身在住所，当船员们发现船长的这一专长之后，他们称这个游戏为“船长的情妇”。
;四子棋是个双人游戏，两人轮流下棋，棋盘由行和列组成的网格，每个选手每次下一个子直到两人中有一人的棋子连成一条水平线、垂直线或者是对角线。
;本实验需要在LC-3中实现简易版四子棋的游戏，两位选手通过键盘和输出窗口轮流交互操作，棋盘由6X 6的网格组成。
;
;游戏规则如下：
;两位选手依次轮流落子;
;选手没有悔棋;
;有子的地方不能继续落子;
;直到有一方的四个棋子能够连成一条水平线、垂直线或者是对角线;
;如果棋盘已满，无人获胜，则平局。
;
;解题:
;游戏是6x6棋盘，连四可以有横，直和斜。
;一行中，六中连四，即是三种方式，６列Ｘ３即１８
;同理，直行也是１８
;斜也是１８
;换言之，全部胜利条利是18*3=54种。
;这样少的条件，直接制作一个表，只要是表内的就是胜利
;6X6共36BIT
;四字是ＤＱ (64BBIT)，即５４个ＤＱ的阵列就是胜利条件表
;样子大约是
;win_table label byte
;dq 111100000000000000000000000000000000b
;这是横列的１个资料
;
;注意:这只是一个范例程式，具备最起码的功能，没有太花巧的技术，也没有人机对战，
;若你需要其他功能或加入或删减任何代码，请随便，但不能要求作者为你订制特定的功能或
;根据功课要求而改变这个子程序改变那个子程序，若是代码错误或优化代码的意见，
;则欢迎提出:)
;
;因为没多少空闲，程序只加了一些简单解释。
;
;Connect Four Chess
.286
Esc_key         equ     1h
up_key          equ     48h ;以下是player2方向键扫瞄码
down_key        equ     50h
left_key        equ     4bh
right_key       equ     4dh
space_key       equ     39h
w_key           equ     11h ;以下是player1方向键扫瞄码
s_key           equ     1fh
a_key           equ     1eh
d_key           equ     20h
n_key           equ     31h
enter_key       equ     1ch
back_color      equ     33h
text_color      equ     3Ah
Title_color     equ     4fh ;2Fh
bottom_color    equ     5Eh
clock_color     equ     5Ah
player1_color   equ     3Fh
player2_color   equ     3Eh
cboard_color    equ     0fh
win_color       equ     0cfh
normal_color    equ     37h
scroll_color    equ     1fh
cur_x    	equ	1b ;35
cur_y           equ     9  ;9
play1_x         equ     3 ;player1资料位置
play1_y         equ     6
play2_x         equ     55 ;player2资料位置
play2_y         equ     6
char_delay      equ     5 ;旋转字符延迟 5/18秒		

CODE_SEG        SEGMENT
                ASSUME  CS:CODE_SEG,DS:CODE_SEG,ES:CODE_SEG
                ORG     100H		;com 档格式
START           PROC    NEAR
                JMP     BEGIN

player1_str     db      'Player 1:X    '
player_L        equ     $ - offset player1_str
                db      '(wsad) - Space'
score1_str      db      'Score:'
p1_score_str    db      '0       '
player2_str     db      'Player 2:O    '
                db      '(',18h,19h,1ah,1bh,') - Enter'    ;方向键的ASCII码
score2_str      db      'Score:'
p2_score_str    db      '0       '
win_str         db      'Player '
who_win         db      '1 Wins !!!',0
win_str_L       equ     $ - offset win_str
tile_str        db      'No one wins !!!',0
clear_win_str   db      win_str_L dup (20h)
player1_score   dw      0
player2_score   dw      0
win_flag        db      0
total_num       dw      0       ;max 36  记录棋盘总棋子数
old_time	dw	0
clock_count	dw	0
char_count	dw	0
Clock_symbol_char1      db   196,'/|\'   ;player1 旋转符
Clock_symbol_char2      db   0fah,0f9h,'0','O';player2 旋转符 
clock_init      dd      0   ;系统时间总数
title1_str label byte
db 1Bh,20h,' Connect Four Chess    ' ;player1 title
title2_str label byte
db '   Connect Four Chess  ',20h,1Ah ;player2 title
title3_str label byte
db 'N-New  Esc-Quit  '
time_str db '   00:00'       ;bottom title

plan label byte ;边框ASCII码，九成九windows editor（dos的可以）不能显示正常边框符，乱码，唯有改为ASCII码
db 218,196,196,196,194,196,196,196,194,196,196,196,194,196,196,196,194,196,196,196,194,196,196,196,191
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 195,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,180
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 195,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,180
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 195,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,180
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 195,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,180
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 195,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,197,196,196,196,180
db 179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179,20h,20h,20h,179
db 192,196,196,196,193,196,196,196,193,196,196,196,193,196,196,196,193,196,196,196,193,196,196,196,217
plan_L equ ($ - offset plan) / 13

win_table label byte ;18 X 3 胜利条件表
;\\\////  左斜和右斜
dq 100000010000001000000100000000000000b
dq 000000100000010000001000000100000000b
dq 000000000000100000010000001000000100b
dq 000100001000010000100000000000000000b
dq 000000000100001000010000100000000000b
dq 000000000000000100001000010000100000b
dq 010000001000000100000010000000000000b
dq 000000010000001000000100000010000000b
dq 000000000000010000001000000100000010b
dq 000010000100001000010000000000000000b
dq 000000000010000100001000010000000000b
dq 000000000000000010000100001000010000b
dq 001000000100000010000001000000000000b
dq 000000001000000100000010000001000000b
dq 000000000000001000000100000010000001b
dq 000001000010000100001000000000000000b
dq 000000000001000010000100001000000000b
dq 000000000000000001000010000100001000b
; ---- 横列
dq 111100000000000000000000000000000000b
dq 000000111100000000000000000000000000b
dq 000000000000111100000000000000000000b
dq 000000000000000000111100000000000000b
dq 000000000000000000000000111100000000b
dq 000000000000000000000000000000111100b
dq 011110000000000000000000000000000000b
dq 000000011110000000000000000000000000b
dq 000000000000011110000000000000000000b
dq 000000000000000000011110000000000000b
dq 000000000000000000000000011110000000b
dq 000000000000000000000000000000011110b
dq 001111000000000000000000000000000000b
dq 000000001111000000000000000000000000b
dq 000000000000001111000000000000000000b
dq 000000000000000000001111000000000000b
dq 000000000000000000000000001111000000b
dq 000000000000000000000000000000001111b
; ||||||直列
dq 100000100000100000100000000000000000b
dq 000100000100000100000100000000000000b
dq 000000100000100000100000100000000000b
dq 000000000100000100000100000100000000b
dq 000000000000100000100000100000100000b
dq 000000000000000100000100000100000100b
dq 010000010000010000010000000000000000b
dq 000010000010000010000010000000000000b
dq 000000010000010000010000010000000000b
dq 000000000010000010000010000010000000b
dq 000000000000010000010000010000010000b
dq 000000000000000010000010000010000010b
dq 001000001000001000001000000000000000b
dq 000001000001000001000001000000000000b
dq 000000001000001000001000001000000000b
dq 000000000001000001000001000001000000b
dq 000000000000001000001000001000001000b
dq 000000000000000001000001000001000001b
win_table_L equ ($ - offset win_table) / 8

board           db      6*6 dup (0)  ;记录棋盘ｘｏ子
last_XO         db      0  ;最后的落子
cursor_size     dw      0
;chess_board     db      6*6 dup (0)     ;0=no player;X(1)=player1,O(-1)=player2
;player_flag     db      0  ;轮到谁下子    ;0=player1 , 1=player2 
cursor_x        dw      0 ;光标位置x
cursor_y        dw      0 ;光标位置y
who_player      db      0   ;轮到谁下子    ;0=player1 , 1=player2            
chessBoardx     equ     1bh - 2 ;棋盘左上角位置
chessBoardy     equ     05h - 1
pos_table       db      chessBoardx + 2  , chessBoardy + 1 ;以下根据chessboardx，y,定义３６格的位置
                db      chessBoardx + 6  , chessBoardy + 1
                db      chessBoardx + 10 , chessBoardy + 1
                db      chessBoardx + 14 , chessBoardy + 1
                db      chessBoardx + 18 , chessBoardy + 1
                db      chessBoardx + 22 , chessBoardy + 1

                db      chessBoardx + 2  , chessBoardy + 3
                db      chessBoardx + 6  , chessBoardy + 3
                db      chessBoardx + 10 , chessBoardy + 3
                db      chessBoardx + 14 , chessBoardy + 3
                db      chessBoardx + 18 , chessBoardy + 3
                db      chessBoardx + 22 , chessBoardy + 3

                db      chessBoardx + 2  , chessBoardy + 5
                db      chessBoardx + 6  , chessBoardy + 5
                db      chessBoardx + 10 , chessBoardy + 5
                db      chessBoardx + 14 , chessBoardy + 5
                db      chessBoardx + 18 , chessBoardy + 5
                db      chessBoardx + 22 , chessBoardy + 5

                db      chessBoardx + 2  , chessBoardy + 7
                db      chessBoardx + 6  , chessBoardy + 7
                db      chessBoardx + 10 , chessBoardy + 7
                db      chessBoardx + 14 , chessBoardy + 7
                db      chessBoardx + 18 , chessBoardy + 7
                db      chessBoardx + 22 , chessBoardy + 7

                db      chessBoardx + 2  , chessBoardy + 9
                db      chessBoardx + 6  , chessBoardy + 9
                db      chessBoardx + 10 , chessBoardy + 9
                db      chessBoardx + 14 , chessBoardy + 9
                db      chessBoardx + 18 , chessBoardy + 9
                db      chessBoardx + 22 , chessBoardy + 9

                db      chessBoardx + 2  , chessBoardy + 11
                db      chessBoardx + 6  , chessBoardy + 11
                db      chessBoardx + 10 , chessBoardy + 11
                db      chessBoardx + 14 , chessBoardy + 11
                db      chessBoardx + 18 , chessBoardy + 11
                db      chessBoardx + 22 , chessBoardy + 11

key_table       db      up_key,down_key,left_key,right_key  ;;方向键扫瞄表
                db      w_key,s_key,a_key,d_key
                db      esc_key,enter_key,space_key,n_key
no_of_key       equ     $ - offset key_table

key_address     dw      offset fup ;;方向键子程序table,会根据按键扫瞄位置，跳到相关子程式
                dw      offset fdown
                dw      offset fleft
                dw      offset fright
                dw      offset ffup    ;w
                dw      offset ffdown  ;s
                dw      offset ffleft  ;a
                dw      offset ffright ;d
                dw      offset fesc
                dw      offset fenter  ;for player 1
                dw      offset fspace  ;for player 2
                dw      offset NewGame
;-------------------- start program ------------------
BEGIN:          call    cls ;清屏
                call    clsc    ;draw background ;画背景色
                mov     ah,3
                xor     bh,bh
                int     10h   ;读光标
                mov     cursor_size,cx
                xor     ch,ch   ;把光标扫瞄线的起始线设０，即扩大光标成方块
                call    setcursz 
                call    get_old_time ;读系统时间总数，用以设定延时和读秒
b2:             mov     win_flag,0 ;重置胜利标志
                call    printTitle  ;绘标题
                call    printplan   ;绘棋盘

b5:             call    printplayer ;显示player资料
b10:            call    OpenCur		;开启光标
                call    setxy		;设定光标位置，初始值是0,0(相对于棋盘)
b20:            mov     ah,1		;测试键盘有否输入
                int     16h			
                jnz     b30			;有
                call    Time_check	;检查时间以显示读秒和旋转文字符等等杂项工作
                jmp     short b20	;再测键盘

b30:            call    input_key	;读键
                call    closeCur	;以下工作需时，关闭光标减少屏幕闪烁
                mov     di,offset key_Table ;键表
                mov     cx,no_of_key
                mov     al,ah
                repnz   scasb	;扫瞄
                jnz     b10		;找不到表中键值，重新读键
                sub     cx,no_of_key
                neg     cx
                mov     bx,cx
                dec     bx
                shl     bx,1
                mov     si,offset key_Address ;指向对应键的子程序
                call    [si+bx] ;跳到相关子程式
                cmp     win_flag,1 ;是否胜利
                jz      b2			;是，重置新局
b5000:          jmp     b5
quit:           call    cls
                mov     ah,4ch		;回DOS
                int     21h
START           ENDP
;----------------------------------------------------
printTitle:			;以下印出标题
                cmp     who_player,0
                mov     bp,offset title1_str
                jz      print_t10
                mov     bp,offset title2_str

print_t10:      mov     cx,plan_L
                mov     dl,chessBoardx
                mov     dh,chessBoardy - 1
                mov     bl,Title_color
                xor     bh,bh
                mov     ax,1300h
                int     10h

print_bottom:   ;call    print_time
                mov     cx,plan_L
                mov     dl,chessBoardx
                mov     bp,offset title3_str
                mov     dh,chessBoardy + 13
                mov     bl,bottom_color
                xor     bh,bh
                mov     ax,1300h
                int     10h
                call    print_time
                ret
;----------------------------------------------------
printplayer:    mov     si,3				;以下印出PLAYER资料，分数
                mov     bp,offset player1_str
                mov     dh,play1_y
                mov     cx,player_L

pp10:           mov     dl,play1_x
                mov     bh,0
                mov     bl,player1_color
                mov     ax,1300h
		int	10h
                inc     dh
                add     bp,Player_L
                dec     si
                jnz     pp10
                ;
                mov     si,3
                mov     bp,offset player2_str
                mov     dh,play2_y
                mov     cx,player_L

pp20:           mov     dl,play2_x
                mov     bh,0
                mov     bl,player2_color
                mov     ax,1300h
		int	10h
                inc     dh
                add     bp,Player_L
                dec     si
                jnz     pp20
		ret
;-----------------------------------------------------
input_key:      xor     ah,ah		;读键
                int     16h
                ret
;-----------------------------------------------------
setxy:          mov     ax,cursor_y			;根据XY指标和POS TABLE拿到真正位置印出光标
                mov     bx,6
                mul     bx
                add     ax,cursor_x
                add     ax,ax
                mov     si,offset pos_table
                add     si,ax
                lodsw
                mov     dx,ax
                call    setcur
                ret
;-----------------------------------------------------
playsound:      push    bx		;以下播放简单音效子程序
                push    di
                push    bp
                mov     bp,7
                mov     di,1100
                mov     bx,35
ps10:           call    sound
                dec     bp
                jz      ps20
                add     di,300
                sub     bx,5
                jmp     short ps10
ps20:           pop     bp
                pop     di
                pop     bx
                ret
;----------------------------------------------------
NewGame:        call    initGame	;按Ｎ后做初始化，再新局
                mov     win_flag,1
                ret
;----------------------------------------------------
fup: ;arrow up					; 按上或w进入此子程序，判断是否最顶，若不是则减１
                cmp     who_player,1
                jnz     ffupx
                jmp     short ffup1
ffup:           cmp     who_player,0  ;w
                jnz     ffupx
ffup1:          cmp     cursor_y,0
                jz      ffupx
                dec     cursor_y
ffupx:          ret
;----------------------------------------------------
fdown: ;arrow down				; 按下或S进入此子程序，判断是否最底,5，若不是则加１
                cmp     who_player,1
                jnz     ffdownx
                jmp     short ffdown1
ffdown:         cmp     who_player,0    ;s
                jnz     ffdownx
ffdown1:        cmp     cursor_y,5
                jae     ffdownx
                inc     cursor_y
ffdownx:        ret
;----------------------------------------------------
fleft: ;arrow left			; 按下左或Ａ进入此子程序，判断是否最左,0，若不是则减１
                cmp     who_player,1
                jnz     ffleftx
                jmp     short ffleft1
ffleft:         cmp     who_player,0    ;a
                jnz     ffleftx
ffleft1:        cmp     cursor_x,0
                jz      ffleftx
                dec     cursor_x
ffleftx:        ret
;----------------------------------------------------
fright: ;arrow right			; 按下或Ｄ进入此子程序，判断是否最左,5，若不是则加１
                cmp     who_player,1
                jnz     ffrightx
                jmp     short ffright1
ffright:        cmp     who_player,0    ;d
                jnz     ffrightx
ffright1:       cmp     cursor_x,5
                jae     ffrightx
                inc     cursor_x
ffrightx:       ret
;----------------------------------------------------
;board           db      36 dup (0)   ;按空白或回车进入此子程序，判断当前位置是否已占用，然后再判断连四

fenter:         cmp     who_player,1	;谁下子
                jnz     fs15            ;ffspacex
                mov     cl,-1			;PLAYER2 标志-1
                mov     last_XO,'O'		;PLAYER2 棋子'0'	
                jmp     short fs10
fspace:         cmp     who_player,0
                jnz     fs15            ;ffspacex
                mov     cl,1
                mov     last_XO,'X'
fs10:           mov     ax,cursor_y	;根据cursor_x,y计算在board记录中是否己占用
                mov     bx,6
                mul     bx
                add     ax,cursor_x
                mov     bx,ax
                mov     si,offset board
                cmp     byte ptr [si+bx],0 ;是否０，若不是０则已占用
fs15:           jnz     ffspacex
                mov     byte ptr [si+bx],cl ;是1或-1
                mov     di,800  ;设定频率
                mov     bx,10   ;设定音效延时，因1/-1不同(player1/2)di和bx以播出不同的音效
                cmp     who_player,0
                jz      fs18
                mov     di,500
                mov     bx,5
fs18:           call    sound	;音效
                call    clear_time_init ;读秒中止，换对方读秒
                inc     total_num		;增加总子数
                cmp     total_num,36 ;check full ? ;是否棋盘满36子 
                jb      fs20		;未满
                call    no_win		;平局
                jmp     short InitGame

fs20:           call    setxy	;设定光标位置
                mov     al,last_XO  ;印出最后下子
                mov     ah,0eh
                int     10h
                call    setxy

                ;check win
                call    check_win	;判断连四
                cmp     win_flag,0	;是否连四了？
                jz      fs30		;没有

initGame:       mov     di,offset board ;完了一局，以下是重置棋盘，初始化所有值
                xor     ax,ax
                mov     cx,6*6
                rep     stosb   ;clear board
                ;mov     who_player,0 ;no need to change, who win who first
                mov     cursor_x,0
                mov     cursor_y,0
                mov     total_num,0
                ;jmp     short ffspacex ;win, next player first

fs30:           xor     who_player,1    ;next player ;换下对方先手
                call    clear_time_init
                call    printTitle
ffspacex:       ret
;------------------------------------------------------
no_win:         mov     win_flag,1		;印出平局
                mov     bp,offset tile_str
                mov     bl,Win_color
                call    clear_win
                call    playsound
                mov     ax,1
                call    delay_proc
                mov     bp,offset clear_win_str
                mov     bl,normal_color
                call    clear_win
                ret
;------------------------------------------------------
Check_win:				;测试连四
                mov     si,offset board		;载入棋盘记录
                mov     cx,6*6
                mov     dl,1            ;player1,测试player1
                call    make_XO			;测试连四
                jc      cw20			;没有，去测试player2
                ;
                ;       player1 win!
                ;
                inc     player1_score		;增加分数
                mov     who_win,'1'	
                mov     di,offset p1_score_str; 印新分数
                xor     dx,dx
                mov     ax,player1_score
                jmp     short cw40

cw20:           mov     si,offset board	;载入棋盘记录	
                mov     cx,6*6
                mov     dl,-1            ;player2
                call    make_XO			;测试连四
                jc      cw50			;没有，离开
                ;
                ;       player2 win!
                ;
                inc     player2_score		;增加分数
                mov     who_win,'2'
                mov     di,offset p2_score_str	;印新分数
                xor     dx,dx
                mov     ax,player2_score

cw40:           mov     win_flag,1		;胜利标志
                call    print_dec		;显示新分数
                call    display_win		;显示谁胜利
                call    playsound		;播音效
                mov     ax,1			;停１秒
                call    delay_proc
                call    playsound 		;再播音效
                mov     ax,1			;停１秒
                call    delay_proc
                mov     bp,offset clear_win_str
                mov     bl,normal_color
		call	clear_win
cw50:           ret
;------------------------------------------------------
make_XO:			;测试连四
.386
                xor     edi,edi
                xor     ebx,ebx
.286
make_XO10:      lodsb			;读入棋盘记录
                cmp     al,dl	;是1或-1?
                jnz     make_xo20 ;不是
                stc					;设定cf=1,准备做rcl，将1bit值 转入ebx,edi组成的64bit
                jmp     short make_xo30
make_xo20:      clc					;设定cf=0,准备做rcl，将0bit值 转入ebx,edi组成的64bit
make_xo30:
.386
                rcl     edi,1   ;ebx,edi = 64bit  ;旋入edi
                rcl     ebx,1					;再旋入edx
                loop    make_XO10			;做36次
                mov     cx,win_table_L		;条件表格长度 = 18 X 3 = 54
                mov     si,offset win_table	;条件表格

make_xo40:      push    edi			;以下是用条件表中的值and掉edx,edi的值，即清除多余，再做比较，若相同则连四
                push    ebx
                mov     eax,[si]
                mov     ebp,[si + 4]
                and     edi,eax
                and     ebx,ebp
                cmp     edi,eax
                jnz     make_xo50
                cmp     ebx,ebp
                jnz     make_xo50
                ;       match !!! ;到此则相同,set cf=0
                pop     ebx
                pop     edi
                clc
                ret

make_xo50:      pop     ebx
                pop     edi
                add     si,8
                loop    make_xo40
                stc     ;no match	;到此，所有条件表中的值都比较了，没有相同，则cf=1
.286
                ret
;-----------------------------------------------------
display_win:    mov     bp,offset win_str		;印出胜利字串
                mov     bl,Win_color

clear_win:      mov     cx,win_str_L
                mov     dl,chessBoardx + 3
                mov     dh,chessBoardy + 16
                xor     bh,bh
                mov     ax,1300h
                int     10h
                ret
;-----------------------------------------------------
fesc:           pop     ax				;离开
                call    quit
                ;
;------------------------------------------------------
setcur:         push    ax				;设定光标
                push    bx
                mov     ah,2
                xor     bh,bh
                int     10h
                pop     bx
                pop     ax
                ret
;-----------------------------------------------------
closecur:       pusha					;关闭光标
                mov     cx,3030h
                call    setcursz
                popa
                ret
;-----------------------------------------------------
OpenCur:        pusha					;开启光标
                mov     cx,cursor_size
                xor     ch,ch
                call    setcursz
                popa
                ret
;-----------------------------------------------------
;chessBoardx     equ     1bh - 2			;印出棋盘
;chessBoardy     equ     09h - 1
printplan:
                mov     si,13   ;row
                mov     bp,offset plan
                mov     cx,plan_l
                mov     dl,chessBoardx
                mov     dh,chessBoardy

pplay_10:       call    print_common
                add     bp,plan_L
                inc     dh
                dec     si
                jnz     pplay_10
                ret
;-----------------------------------------------------
print_common:   mov     bl,scroll_color
                xor     bh,bh
                mov     ax,1300h
                int     10h
                ret
;-----------------------------------------------------
setcursz:       mov     ah,1		
                int     10h
                ret
;------------------------------------------------------
sound:					;以下是音效子程序
;di = freb
;bx = time
                push    ax
                push    bx
                push    cx
                push    dx
                mov     al,0b6h        ;init port 43
		out	43h,al

		mov	dx,14h
		mov	ax,4f38h
		div	di
		out	42h,al
		mov	al,ah
		out	42h,al
		in	al,61h
		mov	ah,al
		or	al,3
		out	61h,al
again:		mov	cx,14546

speaper_on:	loop	speaper_on
		dec	bx
		jnz	again
		mov	al,ah
		out	61h,al
                pop     dx
                pop     cx
                pop     bx
                pop     ax
                ret
;-------------------------------------------------------
put_char:       push    ax			;印出单一字符
                push    bx
                push    cx
                mov     ah,9
                xor     bh,bh
                mov     cx,1
                int     10h
                pop     cx
                pop     bx
                pop     ax
                ret
;-------------------------------------------------------
;output DX:AX,dword (0-FFFFFFFFh / 0-4294967295)	;印出数字
print_dec:  
                xor     cx,cx
                xchg    bp,dx
                mov     si,10 ;div by 10
                mov     bx,30h
print_dec1:
                or      bp,bp
                jz      print_dec3
                xchg    bp,ax
                xor     dx,dx
                div     si
                xchg    bp,ax
                div     si
                or      dl,bl
                push    dx
                inc     cx
                jmp     short print_dec1

print_dec3:     xor     dx,dx
                div     si
                or      dl,bl
                push    dx
                inc     cx
                or      ax,ax
                jnz     print_dec3
print_dec4:
                pop     ax
                stosb
                loop    print_dec4
                ret
;-------------------------------------------------------
delay_proc:     push    es			;迟时子程序，输入AX ,迟时AX秒
                push    dx
                or      ax,ax ;is it zero?
                jz      delayx
                mov     dx,40h
                mov     es,dx
                mov     dx,ax
                add     dx,ax ; x 2
                shl     ax,1  ;x 2
                shl     ax,1  ;x 4
                shl     ax,1  ;x 8
                shl     ax,1  ;x 16
                add     ax,dx ; 16 + 2 = 18
                mov     dx,es:[006ch] ;get system time count
                add     dx,ax ; set limit
delayLoop:
                cmp     es:[006ch],dx ;reach ?
                jbe     delayLoop  ;no, check again
delayx:         pop     dx
                pop     es
                ret
;--------------------------------------------------------
cls:		mov	ah,0fh                  ;get display mode to al ;清屏
		int	10h
		mov	ah,0                    ;Set display mode
		int	10h
		ret
;--------------------------------------------------------
clsc:           mov     ax,0600h                 ;cls   印背景色
                mov     bh,back_color            ;attribute
                mov     cx,0                     ;top left
                mov     dl,80
                mov     dh,60
                int     10h
                ret
;---------------------------------------------------------
;old_time	 dw	 0				;以下是时间子程序，功能是读秒和印出旋转字符
;clock_count	 dw	 0
;char_count	 dw	 0

Time_check:     pusha
                push    es
                mov     ax,40h
                mov     es,ax
                mov     ax,es:[006ch] ;get system time count
                cmp     ax,old_time
                jz      time_checkx
                mov     old_time,ax
                inc     Clock_count             ;no check, direct draw
                cmp     Clock_count,char_delay  ;9 ?
                jb      time_checkx
		mov	Clock_count,0
                inc     char_count
                cmp     char_count,3
                jbe     tc10
                mov     char_count,0

tc10:           mov     ax,1
                mov     bp,offset Clock_symbol_char1
                cmp     who_player,0
                jz      tc20
                mov     al,plan_l - 2
                mov     bp,offset Clock_symbol_char2

tc20:           push    ds
                pop     es
                mov     cx,1
                add     bp,char_count
                mov     dl,chessBoardx
                add     dl,al
                mov     dh,chessBoardy - 1
                mov     bl,Title_color
                xor     bh,bh
                mov     ax,1300h
                int     10h
                ;call    print_bottom
                call    print_time

Time_checkx:    pop     es
                popa
                ret
;---------------------------------------------------------
print_time:     push    es				;显示读秒
.386
                mov     ax,40h
		mov	es,ax
		mov	eax,dword ptr es:[006ch] ;get system time count
		sub	eax,clock_init
		mov	ebx,10
		mul	ebx
		mov	ebx,182
		xor	edx,edx
		div	ebx   ;total seconds
		mov	ebx,60
		xor	edx,edx
		div	ebx   ;ax = min / edx = seconds
		mov	cl,dl ;second
		xor	edx,edx
		div	ebx   ;ax = hour / edx = min
.286
                mov     di,ds
                mov     es,di
		mov	di,offset time_str
		mov	bp,di
		add	al,0
                aam
		or	ax,3030h
		xchg	ah,al
                mov     al,20h
                stosb
                mov     al,1Bh
                cmp     who_player,0
                jz      pt10
                mov     al,1Ah
pt10:           stosb
                mov     al,20h
                stosb
                mov     al,dl
		add	al,0
                aam
		or	ax,3030h
		xchg	ah,al
                stosw
		inc	di
		mov	al,cl
		add	al,0
                aam
		or	ax,3030h
		xchg	ah,al
                stosw
                mov     cx,8
                mov     dl,chessBoardx + 17
                mov     bp,offset time_str
                mov     dh,chessBoardy + 13
                mov     bl,clock_color
                xor     bh,bh
                mov     ax,1300h
                int     10h
                pop     es
                ret
;-------------------------------------------------------
clear_time_init:					;清除读秒
		push	word ptr old_time
		call	get_old_time	;reset clock
		pop	word ptr old_time
		ret
;-------------------------------------------------------
get_old_time:   push    ax			;读取系统总时数
                push    es
                mov     ax,40h
                mov     es,ax
.386
                mov     eax,es:[006ch] ;get system time count
		mov	clock_init,eax
.286
                mov     old_time,ax
		pop	es
                pop     ax
                ret
;--------------------------------------------------------
CODE_SEG        ENDS
                END     START
                
                
                
代码及程式
http://pan.baidu.com/s/1qWOHvpa

